package com.pagoda.nerp.trade.app.account.web;

import com.alibaba.fastjson.JSONObject;
import com.pagoda.nerp.trade.app.account.util.ParamsCheck;
import com.pagoda.nerp.trade.app.account.util.VerifyCodeUtil;
import com.pagoda.nerp.trade.common.BaseResult;
import com.pagoda.nerp.trade.common.ConstantDefine;
import com.pagoda.nerp.trade.common.enums.ErrorCodeMappingEnums;
import com.pagoda.nerp.trade.entity.MdAccount;
import com.pagoda.nerp.trade.entity.MdRole;
import com.pagoda.nerp.trade.entity.MdVendor;
import com.pagoda.nerp.trade.service.*;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;


/**
 * 账户管理模块
 * 
 * @author clh
 *
 */
@Controller
@RequestMapping(value = "/account")
public class AccountMgrController {
	private static final Logger logger = Logger.getLogger(AccountMgrController.class);
	
	@Autowired
	private MdAccountService mdAccountService;

	@Autowired
	private MdVendorService mdVendorService;

	@Autowired
	private MdVendorAccountService mdVendorAccountService;

	@Autowired
	private SysBillRuleService sysBillRuleService;
	
	@Autowired
	private MdRoleService mdRoleService;

	/**
	 * 查询用户微信绑定账户状态
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping("wxBlindState")
	@ResponseBody
	public BaseResult<Object> wxBlindState(@RequestBody Map map,HttpServletRequest request) {
		try {
			String result = ParamsCheck.checkWxBlindState(map);
			if (result.length()>0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS,result);
			}
			
			String openId = map.get("openId").toString();
			MdAccount mdAccount = mdAccountService.queryAccountByOpenId(openId);
			Map<String, Object> data = new HashMap<String, Object>();

			// 是否绑定
			String isBind = "N";
			if (mdAccount != null && "Y".equalsIgnoreCase(mdAccount.getIsBind())) {
				isBind = "Y";
				MdVendor vendorInfo = mdVendorService.selectByCondition(mdAccount.getAccountId());
				data.put("vendorInfo", vendorInfo);
				data.put("account", mdAccount.getAccount());
				data.put("accountType", mdAccount.getAccountType());
				data.put("accountId", mdAccount.getAccountId());
				
				//shiro登录认证
				boolean isAuthenticated = vifityLogin(mdAccount.getAccount(), openId);
				if (!isAuthenticated) {
					return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_ACCOUNT_SHIRO_AUTHENTICATE);
				}
			}

			data.put("isBind", isBind);
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, data);
			
		} catch (Exception e) {
			logger.error("query state that openId blinding account failed:",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}

	/**
	 * 用户注册
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> register(@RequestBody Map map,HttpServletRequest request) {
		try {
			// 校验参数合法性
			String result = ParamsCheck.checkRegister(map);
			if (result.length()>0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS,result);
			}
			
			String vendorName = map.get("vendorName").toString();
			String customerKind = map.get("customerKind").toString();
			String contacts = map.get("contacts").toString();
			String phoneNumber = map.get("phoneNumber").toString();
			String verifyCode = map.get("verifyCode").toString();
			String openId = map.get("openId").toString();
			String cardNo = "";
			String organizationCode = "";
			if (map.containsKey("organizationCode")) {
				organizationCode=map.get("organizationCode").toString();
			}
			
			if (map.containsKey("cardNo")) {
				cardNo = map.get("cardNo").toString();
			}

			// 调用验证码校验接口，校验验证码合法性
			String url = ConstantDefine.SMS_URL + "/sms_module/validateCode";
			JSONObject jsonObj = new JSONObject();
			jsonObj.put("phoneNumber", phoneNumber);
			jsonObj.put("valiCode", verifyCode);
			jsonObj.put("smsType", ConstantDefine.SMS_TYPE_REGISTER);
			int errorCode = VerifyCodeUtil.sendHttpReq(jsonObj.toJSONString(),url);
			if (errorCode != 0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_CODE);
			}

			// 通过手机号判断供应商是否已存在
			int count = mdAccountService.getCountByAccount(phoneNumber);
			if (count > 0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_REPEAT_PHONENUMBER);
			}
			
			Map<String, Object> data = mdVendorService.register(vendorName,customerKind,contacts,phoneNumber,verifyCode,organizationCode,cardNo,openId);
			MdAccount mdAccount = (MdAccount)data.get("account");
			
			//shiro登录认证
			boolean isAuthenticated = vifityLogin(mdAccount.getAccount(), openId);
			if (!isAuthenticated) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_ACCOUNT_SHIRO_AUTHENTICATE);
			}
			
			data.put("account", mdAccount.getAccount());
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, data);

		} catch (Exception e) {
			logger.error("user register failed:", e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
	}

	/**
	 * 用户登录
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> login(@RequestBody Map map,HttpServletRequest request) {
		try {
			// 校验参数合法性
			String result = ParamsCheck.checkLogin(map);
			if (result.length() > 0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS, result);
			}

			String account = map.get("account").toString();
			String verifyCode = map.get("verifyCode").toString();
			String openId= map.get("openId").toString();

			// 调用验证码校验接口，校验验证码合法性
			String url = ConstantDefine.SMS_URL + "/sms_module/validateCode";
			JSONObject jsonObj = new JSONObject();
			jsonObj.put("phoneNumber", account);
			jsonObj.put("valiCode", verifyCode);
			jsonObj.put("smsType", ConstantDefine.SMS_TYPE_LOGIN);
			int errorCode = VerifyCodeUtil.sendHttpReq(jsonObj.toJSONString(), url);
			if (errorCode != 0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_CODE);
			}

			//shiro登录认证
			boolean isAuthenticated = vifityLogin(account, openId);
			if (!isAuthenticated) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_ACCOUNT_SHIRO_AUTHENTICATE);
			}
			
			// 查询用户登录信息
			MdAccount mdAccount = mdAccountService.selectByAccount(account);			
			MdVendor mdVendor = mdVendorService.selectByCondition(mdAccount.getAccountId());
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("vendorInfo", mdVendor);
			data.put("account", mdAccount.getAccount());
			data.put("accountType", mdAccount.getAccountType());
			data.put("accountId", mdAccount.getAccountId());

			//登录账户绑定微信
			if (ConstantDefine.ACCOUNT_BLIANDWX_NO.equals(mdAccount.getIsBind())) {
				mdAccount.setOpenid(openId);
				int resultCode = mdAccountService.updateOpenId(mdAccount);
				if (resultCode<0) {
					return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_DB_DML);
				}
				request.getSession().setAttribute("mdAccount", mdAccount);
			}

			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, data);

		}catch (Exception e) {
			logger.error("user login failed:", e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
	}
	
	
	/**
	 * 用户退出登录
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/logout", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> logout(@RequestBody Map map,HttpServletRequest request) {
		try {
			// 校验参数合法性
			if (null==map.get("account")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}

			map.put("isBind", "N");
			int resultCode = mdAccountService.updateStatus(map);
			if (resultCode<0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_DB_DML);
			}
			Subject subject = SecurityUtils.getSubject();
			subject.logout();
			
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS);

		} catch (Exception e) {
			logger.error("user logout failed:", e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
	}
	
	/**
	 * shiro登录认证
	 * @param phoneNumber
	 * @param openId
	 */
	private boolean vifityLogin(String account,String openId){
		try {
			Subject subject = SecurityUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken(account, openId);
			token.setRememberMe(true);
			subject.login(token);
			subject.getSession().setAttribute("h5ShiroAuthentication",token);
			return subject.isAuthenticated();
		} catch (Exception e) {
			logger.error("shiro authenticate failed.",e);
		}
		
		return false;
	}

	/**
	 * 发送验证码
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/sendMsg", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> sendMsg(@RequestBody Map map) {
		try {
			if (null == map.get("phoneNumber") || null == map.get("smsType")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}
			
			String valiCode = VerifyCodeUtil.createRandomVcode();
			int smsType = Integer.parseInt(map.get("smsType").toString());
			String smsContent="";
			int invalidTime=ConstantDefine.SMS_ACTIVE_TIME*60;
			if (smsType==ConstantDefine.SMS_TYPE_REGISTER) {
				smsContent="尊敬的用户：您在百果园交易平台的注册验证码为："+valiCode+","+invalidTime+"秒内有效。切勿将验证码泄露给他人，感谢您的使用！";
			}else if(smsType==ConstantDefine.SMS_TYPE_LOGIN){
				smsContent="尊敬的用户：您在百果园交易平台的登录验证码为："+valiCode+","+invalidTime+"秒内有效。切勿将验证码泄露给他人，感谢您的使用！";
			}else if(smsType==ConstantDefine.SMS_TYPE_MODIFY){
				smsContent="尊敬的用户：您在百果园交易平台修改资料的验证码为："+valiCode+","+invalidTime+"秒内有效。切勿将验证码泄露给他人，感谢您的使用！";
			}
			String url = ConstantDefine.SMS_URL + "/sms_module/sendMsg";
			JSONObject jsonObj = new JSONObject();
			jsonObj.put("phoneNumber", map.get("phoneNumber").toString());
			jsonObj.put("smsType", smsType);
			jsonObj.put("valiCode", valiCode);
			jsonObj.put("activeTime", ConstantDefine.SMS_ACTIVE_TIME);
			jsonObj.put("smsContent", smsContent);
			
			int errorCode = VerifyCodeUtil.sendHttpReq(jsonObj.toJSONString(),url);
			if (errorCode!=0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_CODE);
			}
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS);
		} catch (Exception e) {
			logger.error("send verifyCode message failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	
	/**
	 * 查询用户注册信息
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/queryUser", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> queryUser(@RequestBody Map map) {
		try {
			// 校验参数合法性
			if (null==map.get("vendorId")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}

			MdVendor vendor = mdVendorService.findMdVendorByCon(map);
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, vendor);
		} catch (Exception e) {
			logger.error("query vendorInfo failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	
	/**
	 * 修改用户注册信息
	 * 
	 * @param mdVendor
	 * @return
	 */
	@RequestMapping(value = "/updateUser", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> updateUser(@RequestBody MdVendor mdVendor,HttpServletRequest request) {
		try {
			// 校验参数合法性
			if (StringUtils.isEmpty(mdVendor.getCustomerKind())
					|| StringUtils.isEmpty(mdVendor.getVendorName())
					|| StringUtils.isEmpty(mdVendor.getContacts())
					|| (StringUtils.isEmpty(mdVendor.getOrganizationCode()) && StringUtils
							.isEmpty(mdVendor.getCardNo()))) {
				
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS, "无效的参数:"+ mdVendor);
			}

			mdVendor.setVerifyStatus(ConstantDefine.VENDOR_VERIFYSTATUS_INI);
			MdAccount account = (MdAccount) request.getSession().getAttribute("mdAccount");
			if (account!=null) {
				mdVendor.setModifyUser(account.getName());
			}
			int result = mdVendorService.updateById(mdVendor);
			if (result<0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_DB_DML,"用户信息更新失败");
			}else {
				return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS);
			}
		} catch (Exception e) {
			logger.error("update vendorInfo failed", e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}

	}
	
	/**
	 * 查询账户信息
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/queryAccount", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> queryAccount(@RequestBody Map map) {
		try {
			// 校验参数合法性
			String result = ParamsCheck.checkAccount(map);
			if (result.length()>0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS,result);
			}
			Integer accountId = Integer.parseInt(map.get("accountId").toString());
			String accountType = map.get("accountType").toString();
			MdVendor vendor = mdVendorService.selectByCondition(accountId);
			if (vendor==null) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_ACCOUNT_NOT_EXIST);
			}
			ArrayList<MdAccount> accountList = new ArrayList<MdAccount>();
			
			//主账户
			if (ConstantDefine.ACCOUNT_TPYE_MAIN.equals(accountType)) {
				accountList= (ArrayList<MdAccount>) mdAccountService.selectByCondition(vendor.getVendorId());
			}
			
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("vendorInfo", vendor);
			data.put("accontList", accountList);
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, data);
		} catch (Exception e) {
			logger.error("query account failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	
	/**
	 * 供应商添加子账户
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/addAccount", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> addAccount(@RequestBody Map map) {
		try {
			// 校验参数合法性
			if (null==map.get("vendorId")||null==map.get("account")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}
			
			Integer vendorId = Integer.parseInt(map.get("vendorId").toString());
			String account = map.get("account").toString();
			int resultCode = mdAccountService.addAccount(account, vendorId);
			if (resultCode<0) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_EXCEPTION_DB_DML,"供应商添加子账户失败");
			}
			
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS);
		} catch (Exception e) {
			logger.error("add account failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	
	
	/**
	 * 查询子账户权限信息
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/queryAccountRoles", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> queryAccountRoles(@RequestBody Map map) {
		try {
			// 校验参数合法性
			if (null==map.get("accountId")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}
			
			Integer accountId = Integer.parseInt(map.get("accountId").toString());
			List<MdRole> mdRoleList = mdRoleService.selectByCondition(accountId);

			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, mdRoleList);
		} catch (Exception e) {
			logger.error("query roles by account failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	
	/**
	 * 查询子供应商审核状态
	 * 
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/queryVendorStatus", method = RequestMethod.POST)
	@ResponseBody
	public BaseResult<Object> queryVendorStatus(@RequestBody Map map) {
		try {
			// 校验参数合法性
			if (null==map.get("vendorId")) {
				return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR_INVALID_PARAMS);
			}
			
			MdVendor vendor = mdVendorService.findMdVendorByCon(map);
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("verifyStatus", vendor.getVendorStatus());
			return new BaseResult<Object>(ErrorCodeMappingEnums.SUCCESS, data);
		} catch (Exception e) {
			logger.error("query roles by account failed",e);
			return new BaseResult<Object>(ErrorCodeMappingEnums.ERROR);
		}
		
	}
	

}
